*******************************************************************************
* PlaySound
*
* (C)  Copyright Apple Computer, Inc. 1988
* All rights reserved.
*
* by Jim MENSCH
* 7/12/88
*
* This program demonstrates how to use the Apple IIgs freeform sound playback
* capabilities. It allows the user to select a file containing a digitized 
* waveform and play it back at any user selected frequency. 
* 
* Files:        system macros and equates
*               PlaySound.init.aii        
*
*
*
* Modification History:
*
* Version 1.0                   Jim Mensch
*
*      7/12/88  Initial Release
*
*      
*
*******************************************************************************


**********************************************************************
*                                                                    *
*             Apple IIGS Source Code Sampler, Volume I               *
*                                                                    *
*             Copyright (c) Apple Computer, Inc. 1988                *
*                       All Rights Reserved                          *
*                                                                    *
*            Written by Apple II Developer Tech Support              *
*                                                                    *
*                                                                    *
*                                                                    *
*  ----------------------------------------------------------------  *
*                                                                    *
*     This program and its derivatives are licensed only for         *
*     use on Apple computers.                                        *
*                                                                    *
*     Works based on this program must contain and                   *
*     conspicuously display this notice.                             *
*                                                                    *
*     This software is provided for your evaluation and to           *
*     assist you in developing software for the Apple IIGS           *
*     computer.                                                      *
*                                                                    *
*     DISCLAIMER OF WARRANTY                                         *
*                                                                    *
*     THE SOFTWARE IS PROVIDED "AS IS" WITHOUT                       *
*     WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,               *
*     WITH RESPECT TO ITS MERCHANTABILITY OR ITS FITNESS             *
*     FOR ANY PARTICULAR PURPOSE.  THE ENTIRE RISK AS TO             *
*     THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH            *
*     YOU.  SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU (AND            *
*     NOT APPLE OR AN APPLE AUTHORIZED REPRESENTATIVE)               *
*     ASSUME THE ENTIRE COST OF ALL NECESSARY SERVICING,             *
*     REPAIR OR CORRECTION.                                          *
*                                                                    *
*     Apple does not warrant that the functions                      *
*     contained in the Software will meet your requirements          *
*     or that the operation of the Software will be                  *
*     uninterrupted or error free or that defects in the             *
*     Software will be corrected.                                    *
*                                                                    *
*     SOME STATES DO NOT ALLOW THE EXCLUSION                         *
*     OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY              *
*     NOT APPLY TO YOU.  THIS WARRANTY GIVES YOU SPECIFIC            *
*     LEGAL RIGHTS AND YOU MAY ALSO HAVE OTHER RIGHTS                *
*     WHICH VARY FROM STATE TO STATE.                                *
*                                                                    *
*                                                                    *
**********************************************************************


                mcopy plays.macros
                copy 2/ainclude/E16.Quickdraw
                copy 2/ainclude/E16.Memory
                copy 2/ainclude/E16.Event
                copy 2/ainclude/E16.Window
                copy 2/ainclude/E16.Dialog

DPHandle       gequ 0           ; handle to Tool Direct Page area
DPPointer      gequ DPHandle+4  ; Pointer to Tool Direct Page area
DeRef          gequ DPPointer+4 ; Temprary Handle dereference area
Temp1          gequ DeRef+4     ; temp DPage storage for general use
ScreenMode     gequ Mode640     ; used to set scan line SCB
ScreenWidth    gequ 640         ; used to set mouse clamps            


;
;   Dialog Item Numbers
;

ItemPlayB      gequ 1
ItemQuitB      gequ 2
ItemLoadB      gequ 3
ItemRad22      gequ 4
ItemRad16      gequ 5
ItemRad11      gequ 6
ItemRad08      gequ 7
ItemRadusr     gequ 8
ItemEditusr    gequ 12
ItemEditVol    gequ 13


                EJECT
*******************************************************************************
*
playSounds      start
*
* Description:  This is the main routine of the program, it calls all
*               other major routines in the proper order.
*
*
* Inputs:       None
*
* Outputs:      None
*
* External Refs:                
*               Import InitTools
*               Import EventLoop
*               Import CloseTools
*               Import QuitParms
*
* Entry Points:
*
*******************************************************************************
                using globals
                jsr InitTools

                _ShowCursor

                jsr EventLoop
                jsr CloseTools

                _Quit QuitParms

                end

                EJECT
*******************************************************************************
*
Globals         data
*
* Description:  Global data for use in all routines of this program
*               This area also contains data used by the init file.
*
*
* Inputs:       None
*
* Outputs:      None
*
* External Refs:                None
*
* Entry Points:
*               Export QuitParms
*
*******************************************************************************
*
* Standard Global Data here
*
*******************************************************************************

TitleString     str 'Apple IIgs Freeform Sound Demo'
AutString       str 'By Mensch Apple DTS (c)1988 Apple Computer'
VersString      str 'Version: 1.0'

MenuHeight      ds 2            ; Stored height of menu bar
MyID            ds 2            ; application ID
MyDP            ds 2            ; My direct page storage

QuitFlag        ds 2
QuitParms       dc i4'0'        ; Pathname of next app
                dc i2'$00'      ; flags

                EJECT
*******************************************************************************
*
* Application specific data
*
*******************************************************************************
theDialog       ds 4            ; pointer to my dialog

MyDialog        ANOP
                dc i2'29,60,189,460'            ; bounds rect...
                dc i2'$FFFF'    ; true visible
                dc i4'0'        ; refcon=0
                dc i4'PlayB'    ; Item 1
                dc i4'QuitB'    ; Item 2
                dc i4'LoadB'    ; Item 3
                dc i4'K22B'
                dc i4'K16B'
                dc i4'K11B'
                dc i4'K08B'
                dc i4'KUsrB'
                dc i4'KUsrE'
                dc i4'KVolE'
                dc i4'KVolS'
                dc i4'STit'
                dc i4'NPStat'
                dc i4'0'        ; end of list!

PlayBTitle      str 'Play'
PlayB           ANOP
                dc i2'1'
                dc i2'145,330,155,390'
                dc i2'ButtonItem'               ; standard button
                dc i4'PlayBTitle'
                dc i2'0'
                dc i2'0'        ; item flag
                dc i4'0'        ; no color table

quitBTitle      str 'Quit'
quitB           ANOP
                dc i2'2'
                dc i2'130,330,140,390'
                dc i2'ButtonItem'               ; standard button
                dc i4'quitBTitle'
                dc i2'0'
                dc i2'0'        ; item flag
                dc i4'0'        ; no color table

LoadBTitle      str 'Load...'
LoadB           ANOP
                dc i2'3'
                dc i2'115,330,125,390'
                dc i2'ButtonItem'               ; standard button
                dc i4'LoadBTitle'
                dc i2'0'
                dc i2'0'        ; item flag
                dc i4'0'        ; no color table

K22BTitle       str '22 Khz'
K22B            ANOP
                dc i2'4'
                dc i2'30,10,40,190'
                dc i2'radioItem'                ; radio button
                dc i4'K22BTitle'
                dc i2'0'
                dc i2'1'        ; item flag: Family 1
                dc i4'0'        ; no color table

K16BTitle       str '16 Khz'
K16B            ANOP
                dc i2'5'
                dc i2'45,10,55,190'
                dc i2'radioItem'                ; radio button
                dc i4'K16BTitle'
                dc i2'0'
                dc i2'1'        ; item flag
                dc i4'0'        ; no color table

K11BTitle       str '11 Khz'
K11B            ANOP
                dc i2'6'
                dc i2'60,10,70,190'
                dc i2'radioItem'                ; radio button
                dc i4'K11BTitle'
                dc i2'0'
                dc i2'1'        ; item flag:Family 1
                dc i4'0'        ; no color table

K08BTitle       str ' 8 Mhz'
K08B            ANOP
                dc i2'7'
                dc i2'75,10,85,190'
                dc i2'radioItem'                ; radio button
                dc i4'K08BTitle'
                dc i2'0'
                dc i2'1'        ; item flag: family 1
                dc i4'0'        ; no color table

KUsrBTitle      str 'User Supplied :$'
KUsrB           ANOP
                dc i2'8'
                dc i2'90,10,100,150'            
                dc i2'radioItem'                ; radio button
                dc i4'KUsrBTitle'
                dc i2'0'
                dc i2'1'        ; item flag: family 1
                dc i4'0'        ; no color table


KUsrEDef        str '00FF'
KUsrE           ANOP
                dc i2'12'
                dc i2'88,150,102,190'
                dc i2'editLine'
                dc i4'KUsrEDef'
                dc i2'4'        ; maximum length of             edit item
                dc i2'0'        ; item flag
                dc i4'0'        ; no color table

KVolEDef        str '00FF'
KVolE           ANOP
                dc i2'13'
                dc i2'28,250,42,290'
                dc i2'editLine+itemDisable'
                dc i4'KVolEDef'
                dc i2'4'
                dc i2'0'        ; item flag
                dc i4'0'        ; no color table

STittitle       str 'Digitized sound player By Jim Mensch Apple II DTS'
STit            ANOP
                dc i2'9'
                dc i2'1,10,11,380'
                dc i2'statText+itemDisable'
                dc i4'STitTitle'
                dc i2'0'
                dc i2'0'
                dc i4'0'


NPTitle         str 'Now Playing:^0    '
NPNoFile        str 'No files loaded'
NPStat          ANOP
                dc i2'10'
                dc i2'12,10,22,300'
                dc i2'statText+itemDisable'
                dc i4'NPTitle'
                dc i2'0'
                dc i2'0'
                dc i4'0'

KVolSTit        str 'Volume:$'
KVolS           ANOP
                dc i2'11'
                dc i2'30,180,40,240'
                dc i2'statText+itemDisable'
                dc i4'KVolSTit'
                dc i2'0'
                dc i2'0'
                dc i4'0'


Rect            ds 8
MyRect          ds 8

PromptStr       str 'Hello'                ; SFGetFile record
MyReply         ANOP
MyRGood         ds 2
MyRFType        ds 2
MyRAType        ds 2
MyRName         ds 16
MyRFName        ds 129


OPParms         ANOP
OPRefNum        dc i2'0'        ; ProDOS 16 open call parm block
                dc i4'MyRFName'
                dc i4'0'
GEParms         ANOP
GERefNum        dc i2'0'        ; ProDOS 16 GetEOF Parm block
GESize          dc i4'0'

RDParms         ANOP            ; ProDOS 16 read parm block
RDRefNum        dc i2'0'
RDDataBuf       dc i4'0'
RDReqCnt        dc i4'0'
                dc i4'0'
CLParms         ANOP
CLRefNum        dc i2'0'        ; ProDOS 16 close parm block

; Record used for FFStartsound to describe the freeform wave

MyFFRecord      dc i4'0'        ; address of wave
                dc i2'0'        ; size of wave in pages..
Rate            dc i2'$1AC'     ; sample rate 22Khz
                dc i2'$0100'    ; DOC starting address
                dc i2'$8000'    ; DOC buffer size
                dc i4'0'
Vol1            dc i2'$00FF'    ; kinda medium..

; Table of standard sampling rates 
;                    22khz,16khz,11khz, 8khz, filler
RateTable       dc i2'$01ac,$0137,$00D6,$009C,$0000,$0000'

                end

                EJECT
*******************************************************************************
*
EventLoop       start
*
* Description:  This is the main routine of the program. It creates a
*               Dialog box and handles all user selections that occur. When
*               the user selects quit, this routine exits and the program
*               will then end.
*
*
* Inputs:       None
*
* Outputs:      None
*
* External Refs:
*               Import SFLoop
*               Import PlaySound
*
* Entry Points: None
*
*******************************************************************************
                using Globals

                PushLong #0     ; create the dialog             this program
                PushLong #MyDialog              ; revolves around from a template
                _GetNewModalDialog
                PullLong theDialog              ; store its pointer             into theDialog

                lda #ItemRad22  ; reset radio buttons to the initial
                jsr RadHit      ; state of 22Khz default freq.

                PushLong #NPNoFile              ; set the Paramtext ^0 item to
                PushLong #0     ; the initial file name of "no file"  
                PushLong #0
                PushLong #0
                _ParamText

EL0010          PushWord #0     ; now wait for a selection by the user
                PushLong #0
                _ModalDialog
                pla             ; recover the item hit from the stack

                cmp #ItemPlayB  ; is it the play button?
                bne EL0020      ; if not test next button
                jsr PlaySound   ; if it was the play button then play
                bra EL0010      ; the saved sound and get another hit

EL0020          ANOP
                cmp #ItemQuitB  ; is it the quit button?
                bne EL0030      ; if not test next button
                bra ELDone      ; if it was, end the program

EL0030          ANOP
                cmp #ItemLoadB  ; is it the load button?
                bne EL0040      ; if not test usr Rate item
                jsr SFLoop      ; if so, ask user for a new sound file
                bra EL0010      ; and get another hit

EL0040          ANOP
                cmp #ItemEditUsr                ; see if the user changed the usr rate
                bne EL0050      ; if not test radio buttons
                jsr SetUsr      ; if so, get the new value
                bra EL0010
EL0050          ANOP
; If we get this far, the only thing we have left to test for is radio buttons
; and the radio buttons are items 4-8
                cmp #9          ; test to see if 3<ItemHit<9
                bge EL0060      ; if not then skip the next line
                jsr RadHit      ; if so then a radio button was hit
                bra EL0010      ; handle it and get another hit

EL0060          ANOP
                brl EL0010      ; this should not occur since no other
;                                 items are enabled

; When the user selects quit the program branches here to close the dialog
; and go back and close down the program
ELDone          ANOP
                PushLong theDialog              ; close the dialog and dispose of all
                _CloseDialog    ; memory used by it
                rts             ; and return to the main loop

; RadHit is called when the user selects any radio button. This routine
; turns off all radio buttons and turns on the one that the user hit.
; It then finds the correct value for the selected rate in RateTable
; and inserts  it into the waveform data.
; If the user selects the "User Supplied" sampling rate option, This
; routine will call SetUsr to obtain the users rate value.
RadHit          ANOP
                sta temp1       ; save the item hit             number

;               PushWord #0     ; and turn off all radio buttons
;               PushLong theDialog
;               PushWord #ItemRad22
;               _SetDItemValue;;
;
;               PushWord #0
;               PushLong theDialog
;               PushWord #ItemRad16
;               _SetDItemValue;
;
;               PushWord #0
;               PushLong theDialog
;               PushWord #ItemRad11
;               _SetDItemValue
;
;               PushWord #0
;               PushLong theDialog
;               PushWord #ItemRad08
;               _SetDItemValue
;
;               PushWord #0
;               PushLong theDialog
;               PushWord #ItemRadusr
;               _SetDItemValue

                PushWord #1     ; now turn on the radio button that 
                PushLong theDialog              ; was hit
                PushWord temp1
                _SetDItemValue

                lda temp1       ; Check to see if the user button was hit
                cmp #ItemRadUsr
                beq SetUsr1     ; if so, get the user rate
                sec             ; if not, get the new sampling rate
                sbc #4          ; subtract 4 from choice
                asl a           ; multiply it by 2
                tax             ; use it as an index
                lda RateTable,x
                sta Rate
                rts

; This routine gets the users input value from the "User Supplied" edit line item
; converts it to an integer and stores it as the current sampling rate
SetUsr          ANOP
                PushWord #1
                PushLong theDialog
                PushWord #ItemRadUsr
                _SetDItemValue
SetUsr1         ANOP
                PushLong theDialog              ; get the text from             the user sampleing
                Pushword #ItemEditUsr ; rate item
                PushLong #tempAns
                _GetIText

                PushWord #0     ; and convert it to             an integer
                PushLong #tempAns+1             ; Skip the length byte
                lda tempAns     ; push the length byte seperately
                and #$00FF      ; after stripping off extra data
                pha
                _Hex2Int

                pla             ; store this number             as the new rate
                sta Rate
                rts
tempAns         ds 8

                end


                EJECT
*******************************************************************************
*
LoadSound       start
*
* Description:  startedure that loads a selected file from disk and stores
*               it in RDDataBuf.
*
*
* Inputs:       MyRFName should contain the full pathname of the file to load
*
* Outputs:      Data in the handle RDDataBuf
*
* External Refs:
*               Import PDosError
*               Import ToolError
*
* Entry Points: None
*
*******************************************************************************
                using Globals

                lda RDDataBuf   ; check handle to see if its already 
                ora RDDataBuf+2 ; allocated by seeing if its 0
                beq LS0010      ; if it is, skip next line

                PushLong RDDataBuf              ; if non-zero then de-allocate
                _DisposeHandle  ; the memory

LS0010          ANOP
                _Open OpParms   ; open the file chosen by user
                bcc LS0015      ; no error, branch around next line
                jsr PDosError   ; got error, report to user
                brl LoadDone    ; and end this routine

LS0015          ANOP
                lda OPRefNum    ; save the file ref             number into all
                sta RDRefNum    ; the other parm blocks 
                sta GERefNum
                sta CLRefNum
 
; Now that the file is opened we ask ProDOS for the length of the file.
; Once recieved we create a handle to read the data into and update the FFRecord
; to reflect the size and location of the data.

                _Get_EOF GEParms                ; Find out how big the file is
                bcc LS0020      ; so we can create the right sized buffer
                jsr PDosError   ; we got an error, so report it and...
                brl LoadCDone   ; file open was succesfull, so close it
LS0020          ANOP
                lda GESize      ; first, update the read request count so
                sta RDReqCnt    ; read call knows how much to load
                lda GESize+2    ; Now get the high word of the file size
                sta RDReqCnt+2  ; and finish updating the read parms
                lda RdReqCnt+1  ; get the number of 256 byte pages
                sta MyFFRecord+4                ; and update the FFRecord

                PushLong #0     ; reserve memory for the waveform
                PushLong GESize
                PushWord MyID
                PushWord #%1100000000001100
                PushLong #0
                _NewHandle
                bcc LS0025
                jsr ToolError
                brl LoadCDone

LS0025          ANOP
                pla             ; dereference the handle to get the
                sta DeRef       ; pointer
                pla
                sta DeRef+2

                lda [DeRef]
                sta RDDataBuf   ; store the pointer into the read parms 
                sta MyFFRecord  ; and the FFRecord

                ldy #2
                lda [DeRef],y
                sta RDDataBuf+2
                sta MyFFRecord+2

                _Read RDParms   ; Read the data from the file
                bcc LS0030
                jsr PDosError
                brl LoadCDone
LS0030          ANOP
LoadCDone       ANOP
                _Close CLParms  ; and finally close the file
                bcc LoadDone
                jsr PDosError
LoadDone        ANOP
                rts             ; and leave

                end

                EJECT
*******************************************************************************
*
PlaySound       start
*
* Description:  Tell the sound managerto start the digitized sound
*               descripbed by myFFRecord
*
*
* Inputs:       None
*
* Outputs:      None
*
* External Refs:                
*               Import ToolError
*
* Entry Points: None
*
*******************************************************************************
                using Globals

                PushLong theDialog              ; get the volume from the Dialog
                Pushword #ItemEditVol ; box. 
                PushLong #tempAns               ; 
                _GetIText

                PushWord #0     ; convert the ASCII             hexidecimal value to
                PushLong #tempAns+1             ; an integer.
                lda tempAns     ; load length of the string
                and #$00FF      ; strip off the high byte
                pha             ; and push it onto the stack as out length
                _Hex2Int

                pla
                sta Vol1        ; store this value into our volume


                PushWord #$0001 ; stop gen 0
                _FFStopSound

                PushWord #$0001 ; and start the sound at gen 0
                PushLong #MyFFRecord
                _FFStartSound
                bcc PS0010      ; if no error then just end
                jsr ToolError   ; However, if an error occured report it
PS0010          ANOP
                rts

tempAns         ds 8            ; temporary storage for the str convert

                end

**********************************************************************************
*
*   SFLoop -    Throw up a sfGetFile dialog and let the user select file of
*               their choice.
*
                EJECT
*******************************************************************************
*
SFLoop          start
*
* Description:  Call SFGetFile to obtain the users choice of sound file
*               to playback. If the user selects a valid file, load it and
*               play it. If the user selects cancel, do nothing.
*
*
* Inputs:       None
*
* Outputs:      None
*
* External Refs:                
*               Import LoadSound
*               Import PlaySound
*
* Entry Points:
*
*******************************************************************************
                using Globals

                PushWord #30    ; Location of dialog on screen
                PushWord #30

                PushLong #promptStr             ; promtp for within             the dialog
                PushLong #0     ; no filter proc
                PushLong #0     ; no type list
                PushLong #MyReply               ; record to put user selection
                _SFGetFile

                lda MyRGood     ; test if cancel hit...
                sta QuitFlag    ; save it in quitflag
                beq SFQuit      ; and just quit

                jsr LoadSound   ; Now load the file             into the buffer
                jsr PlaySound   ; and play the loaded file


                PushLong #MyRName               ; set Param ^0 as the name of the
                PushLong #0     ; file for display in the didlog box
                PushLong #0
                PushLong #0
                _ParamText

SFQuit          rts
                end

                EJECT
*******************************************************************************
*
PDosError       start
*
* Description:  Reports an error to the user and calls it a ProDos error.
*
*
* Inputs:       <A> - error code to report
*
* Outputs:      None
*
* External Refs:                None
*
* Entry Points: None
*
*******************************************************************************
                using Globals

                pha             ; and convert the error to a string
                PushLong #ErrorNum
                PushWord #4
                _Int2Hex
                
; Use the window manager AlertWindow call to report the error message
                pha             ; space for result
                PushWord #0     ; we are using P-Strings
                PushLong #SubStringA
                PushLong #AlertStr
                ldx #$590E      ; _AlertWindow
                jsl $E10000
                pla             ; pull off button hit


                rts
tempError       ds 2
SubStringA      dc i4'ErrorNum' ; substitution string array
ErrorNum        dc c'xxxx',i1'0'
AlertStr        dc c'24/ProDOS Error Loading File #*0/^#6'
                dc i1'0'

                end

                EJECT
*******************************************************************************
*
ToolError       start
*
* Description:  Report an error to the user and say it was a tool error.
*
*
* Inputs:       <A> error number to report
*
* Outputs:      None
*
* External Refs:                None
*
* Entry Points: None
*
*******************************************************************************
                using Globals

                pha
                PushLong #ErrorNum
                PushWord #4
                _Int2Hex

                pha             ; space for result
                PushWord #0     ; we are using P-Strings
                PushLong #SubStringA
                PushLong #AlertStr
                ldx #$590E      ; _AlertWindow
                jsl $E10000
                pla             ; pull off button hit


                rts
SubStringA      dc i4'ErrorNum' ; substitution string array
ErrorNum        dc c'xxxx',i1'0'
AlertStr        dc c'24/Tool Error #*0/^#6'
                dc i1'0'

                end

                copy PlayS.init.aii

                END
